package main

import (
	"edata-hub/pkg/raft"
	"edata-hub/pkg/raft/services"
	"edata-hub/pkg/server"
	"flag"
	"fmt"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"gopkg.in/yaml.v3"
	"io"
	"os"
	"strings"
)

func ReadConfig(path string) (server.Config, error) {
	var config server.Config
	file, openFileErr := os.Open(path)
	defer file.Close()
	if openFileErr != nil {
		return config, openFileErr
	}
	data, readFileErr := io.ReadAll(file)
	if readFileErr != nil {
		return config, readFileErr
	}
	unmarshalErr := yaml.Unmarshal(data, &config)
	if unmarshalErr != nil {
		return config, unmarshalErr
	}
	return config, nil
}
func main() {

	var command string
	flag.StringVar(&command, "command", "CLUSTER_NODES_SEARCH", "Command from client")
	var params string
	flag.StringVar(&params, "params", "comp=hadoop-3.3.4,id=FGU-p7dp4MupeLVWuz7Iu", "Params from client")
	flag.Parse()
	config, _ := server.ReadConfig("configs/application.yml")
	msg := &raft.Message{
		PrintLevel: config.RaftConfig.MsgLevel,
	}
	cmd, params_map, analyze_err := AnalyzeCmdAndParams(command, params)
	if analyze_err != nil {
		msg.Error("parameters are not legal:%s", analyze_err.Error())
	}
	server_addr := config.RaftConfig.Ip + ":" + config.RaftConfig.RpcPort
	client, createClientErr := CreateRaftGRPCClient(server_addr)
	if createClientErr != nil {
		msg.Error("create rpc client of server %s:%s", server_addr, createClientErr.Error())
		return
	}
	req := &services.CommandReq{
		Command: cmd,
		Params:  params_map,
	}
	stream, sendCmdErr := client.OnHandleCommand(context.Background(), req)
	if sendCmdErr != nil {
		msg.Error("cannot send command to server %s:%s", server_addr, sendCmdErr.Error())
		return
	}
	for {
		result, err := stream.Recv()
		if err != nil {
			msg.Error("cannot require stream from server")
			break
		}
		if result.Status == -1 {
			msg.Error("%s", strings.TrimSpace(result.Msg))
			break
		} else if result.Status == 2 {
			msg.Info("all commands have been executed")
			break
		} else {
			msg.Info("%s", strings.TrimSpace(result.Msg))
			if strings.TrimSpace(result.Results) != "" {
				fmt.Println(result.Results)
			}
		}
	}
}

func CreateRaftGRPCClient(addr string) (services.RaftServiceClient, error) {
	conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		return nil, err
	}
	client := services.NewRaftServiceClient(conn)
	return client, nil
}

func AnalyzeCmdAndParams(cmd string, params string) (string, map[string]string, error) {
	param_map := make(map[string]string)
	for _, kv := range strings.Split(params, ",") {
		k_v := strings.Split(kv, "=")
		if cmd == "DATACOMP_INSTALL" {
			data, err := os.ReadFile(k_v[1])
			if err != nil {
				return "", nil, err
			}
			k_v[1] = strings.ReplaceAll(string(data), "\r", "")
			k_v[1] = strings.ReplaceAll(k_v[1], "\n", "")
			k_v[1] = strings.ReplaceAll(k_v[1], " ", "")
		}
		param_map[k_v[0]] = k_v[1]
	}
	return cmd, param_map, nil
}
